home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include "ip.h"
- #include "icmp.h"
- #include "timer.h"
-
- #include "nettrace.h"
-
-
- #define noDEBUG
-
- static void pingtmo(TIMER);
- static int icmp_pingstate;
- static TIMER icmp_pingtm;
- static int pingseq;
- static PACKET *sent;
- static int snt_len;
- struct redent redtab[REDIRTABLEN];
- int rednext = 0;
- int holdback = 0;
- long icmp_counts[2] = {0L,0L};
-
- int icmp_init(void)
- {
- int i;
- if(!ip_open(IP_ICMP,icmp_handler,(int (*)(IP *))NULL)) return(FALSE);
- icmp_pingstate = PGWAITING;
- for(i=0; i< REDIRTABLEN; i++)
- redtab[i].dst_inaddr = 0L;
- return(TRUE);
- }
-
-
- int icmp_handler(PACKET *pkt,int len,INADDR fhost)
- {
- register IP *ip;
- register struct ping *e;
- struct redirect *rd;
- struct destun *pdp;
- u_short osum;
- char *data1, *data2;
- int i;
-
- ip = ip_head(pkt);
- e = (struct ping *)ip_data(pkt);
-
- osum = e->pchksum;
- e->pchksum = 0;
-
- if(chksum((u_short *)e,len,0) != osum)
- {
- ip_free(pkt);
- return(FALSE);
- }
- e->pchksum = osum;
- icmp_counts[0]++;
-
- switch(e->ptype)
- {
- case ICMP_ECHOREQ: /* ping */
- e->ptype = ICMP_ECHOREP;
- e->pchksum = 0;
- e->pchksum = chksum((u_short *)e,len,0);
- ip->src_inaddr = ip->dst_inaddr;
- ip->dst_inaddr = fhost;
- icmp_counts[1]++;
- i = ip_send(IP_ICMP, pkt, len, fhost);
- ip_free(pkt);
- return(i);
-
- case ICMP_DESTIN:
- pdp = (struct destun *)e;
- ip_dudemux(&pdp->dip); /* DDP - upcall handler */
- break;
-
- case ICMP_SOURCEQ:
- holdback++; /* hold back data - dst busy */
- break;
-
-
- case ICMP_REDIR:
- rd = (struct redirect *)e;
- for(i=0; i<REDIRTABLEN; i++)
- if(redtab[i].dst_inaddr == rd->rdip.dst_inaddr)
- {
- redtab[i].gw_inaddr = rd->rdgw;
- ip_free(pkt);
- return(TRUE);
- }
- redtab[rednext].dst_inaddr = rd->rdip.dst_inaddr;
- redtab[rednext].gw_inaddr = rd->rdgw;
- rednext++;
- if(rednext >= REDIRTABLEN) rednext = 0;
- break;
-
-
- case ICMP_ECHOREP:
- if(e->pseq != pingseq-1)
- {
- ip_free(pkt);
- return(FALSE);
- }
- data1 = ((ICMP_PACKET *)pkt)->icmp_data;
- data2 = ((ICMP_PACKET *)sent)->icmp_data;
- for(i=0; i < snt_len; i++)
- if(*data1++ != *data2++)
- {
- icmp_pingstate = PGBADDATA;
- ip_free(pkt);
- return(FALSE);
- }
-
- icmp_pingstate = PGSUCCESS;
- ip_free(pkt);
- break;
-
- case ICMP_TIMEX:
- break;
-
- case ICMP_PARAM:
- break;
-
- case ICMP_TIMEREQ:
- e->ptype = ICMP_TIMEREP;
- e->pchksum = 0;
- e->pchksum = chksum((u_short *)e, (int)sizeof(struct tstamp),0);
- ip->src_inaddr = ip->dst_inaddr;
- ip->dst_inaddr = fhost;
- icmp_counts[1]++;
- i = ip_send(IP_ICMP, pkt, (int)sizeof(struct tstamp), fhost);
- ip_free(pkt);
- return(i);
-
- case ICMP_INFO:
- break;
-
- }
- ip_free(pkt);
- return(TRUE);
- }
-
-
-
- int icmp_dstun(INADDR inaddr ,IP *ip,int type)
- {
- PACKET *p;
- register struct destun *d;
- int i;
-
- p = ip_alloc(512, 0);
- if(p == NULL) return 0;
-
- d = (struct destun *)ip_data(p);
- d->dtype = ICMP_DESTIN;
- d->dcode = type;
- for(i=0; i<(int)sizeof(IP)+8; i++)
- ((char *)&d->dip)[i] = ((char *)ip)[i];
- d->dchksum = 0;
- d->dchksum = chksum((u_short *)d, (int)sizeof(struct destun),0);
- icmp_counts[1]++;
- i = ip_send(IP_ICMP, p, (int)sizeof(struct destun), inaddr);
- ip_free(p);
- return(i);
- }
-
-
- icmp_ping(INADDR fhost, int length)
- {
- PACKET *p;
- register struct ping *e;
- register char *data;
- int i;
-
- p = ip_alloc(40, 0);
-
- if(p == NULL)
- {
- return PGNOSND;
- }
- e = (struct ping *)ip_data(p);
- e->ptype = ICMP_ECHOREQ;
- e->pcode = 0;
- e->pid = 0;
- e->pseq = pingseq++;
-
- /* Put 256 random numbers in the packet. */
- data = ip_data(p) + ICMP_PKTSIZE;
- for(i=0; i<length; i++) *data++ = rand();
-
- /* Calculate the checksum */
- e->pchksum = 0;
- if((ICMP_PKTSIZE+length)&1)
- *data = 0;
- e->pchksum = chksum((u_short *)e, (ICMP_PKTSIZE+length+1),0);
- icmp_pingstate = PGWAITING;
- sent = p;
- snt_len = length;
- icmp_pingtm = tm_alloc();
- if(icmp_pingtm < 0)
- {
- ip_free(p);
- return(PGNOSND);
- }
- tm_set(tm_msec(ECHO_TIMEOUT), pingtmo, icmp_pingtm );
- icmp_counts[1]++;
- if(ip_send(IP_ICMP, p, ICMP_PKTSIZE+length, fhost) <= 0)
- {
- tm_free(icmp_pingtm );
- ip_free(p);
- return(PGNOSND);
- }
- while(icmp_pingstate == PGWAITING)
- net_demux(FALSE,DEMUX);
- tm_free(icmp_pingtm );
- ip_free(p);
- sent = 0;
- return(icmp_pingstate);
- }
-
- static void pingtmo(TIMER tm)
- {
- if(icmp_pingtm == tm)
- icmp_pingstate = PGTMO;
- }
-